package uk.co.threekelvin.perihelion;

import uk.co.threekelvin.perihelion.engine.World;
import uk.co.threekelvin.perihelion.graphics.Render;
import uk.co.threekelvin.perihelion.input.Keyboard;
import uk.co.threekelvin.perihelion.input.Mouse;

public class Game implements Runnable {

	public static int width = 256;
	public static int height = width * 9 / 16;
	public static int scale = 4;

	public final String TITLE = "Perihelion";
	public final double TICKRATE = 60.0;

	private Thread thread;
	private boolean running = false;

	private World world;
	private Render render;
	private Keyboard keyboard;
	private Mouse mouse;

	public Game() {
		world = new World(1024, 1024);
		render = new Render(width, height, scale);
		keyboard = new Keyboard();
		mouse = new Mouse();

		render.addKeyListener(keyboard);
		render.addMouseListener(mouse);

		start();
	}

	public synchronized void start() {
		running = true;
		thread = new Thread(this);
		thread.start();
	}

	public synchronized void stop() {
		running = false;
		try {
			thread.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public void run() {
		double nextTick = System.nanoTime();
		final double INTERVAL = 1e9 / TICKRATE;

		int frames = 0, ticks = 0;

		while (running) {
			while (System.nanoTime() >= nextTick) {
				tick();
				ticks++;
				nextTick += INTERVAL;
			}

			render();
			frames++;

			if (ticks >= TICKRATE) {
				render.setTitle(TITLE + " | " + frames + " fps");
				frames = 0;
				ticks = 0;
			}
		}
	}

	private void tick() {
		if (keyboard.isInputPressed("left")) {
			render.xOffset--;
			if (render.xOffset <= 0) render.xOffset = 0;
		}
		if (keyboard.isInputPressed("right")) {
			render.xOffset++;
			if (render.xOffset > world.getWidth()) render.xOffset = world.getWidth();
		}
		if (keyboard.isInputPressed("up")) {
			render.yOffset--;
			if (render.yOffset <= 0) render.yOffset = 0;
		}
		if (keyboard.isInputPressed("down")) {
			render.yOffset++;
			if (render.yOffset > world.getHeight()) render.yOffset = world.getHeight();
		}

		world.physics();
	}

	private void render() {
		render.render(world);
	}

	public static void main(String[] args) {
		new Game();
	}

}
